package hyl.core.fun;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import hyl.core.MyFun;
import hyl.core.safe.MyHash;

public class MyHostInfo {
	static MyHostInfo mhi = null;

	public static MyHostInfo instance() {
		if (mhi == null)
			mhi = new MyHostInfo();
		return mhi;
	}

	String cpuid = null;
	String mainboard = null;
	String disk = null;
	String mac = null;
	String uu = null;

	private MyHostInfo() {
		cpuid = doCPU序列号();
		mainboard = do主板序列号();
		disk = do硬盘序列号("c");
		mac = do网卡地址();
		uu = MyFun.join(cpuid, mainboard, disk);
	}

	public String getCPU序列号() {
		return cpuid;
	}

	public String get主板序列号() {
		return mainboard;
	}

	public String get硬盘序列号() {
		return disk;
	}

	public String get网卡地址() {
		return mac;
	}

	/**
	 * 获取主板序列号
	 * 
	 * @return
	 */
	public String do主板序列号() {
		String result = "";
		if (isLinux())
			return getLinux序列号("dmidecode |grep 'Serial Number'", "Serial Number", ":");
		try {
			File file = File.createTempFile("realhowto", ".vbs");
			file.deleteOnExit();
			FileWriter fw = new java.io.FileWriter(file);

			String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
					+ "Set colItems = objWMIService.ExecQuery _ \n" + "   (\"Select * from Win32_BaseBoard\") \n"
					+ "For Each objItem in colItems \n" + "    Wscript.Echo objItem.SerialNumber \n"
					+ "    exit for  ' do the first cpu only! \n" + "Next \n";

			fw.write(vbs);
			fw.close();
			String path = file.getPath().replace("%20", " ");
			Process p = Runtime.getRuntime().exec("cscript //NoLogo " + path);
			BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String line;
			while ((line = input.readLine()) != null) {
				result += line;
			}
			input.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result.trim();
	}

	/**
	 * 获取硬盘序列号(该方法获取的是 盘符的逻辑序列号,并不是硬盘本身的序列号) 硬盘序列号还在研究中
	 * 
	 * @param drive 盘符
	 * @return
	 */
	public static String do硬盘序列号(String drive) {
		String result = "";
		if (isLinux())
			return getLinux序列号("fdisk -l", "Disk identifier", ":");
		try {
			File file = File.createTempFile("realhowto", ".vbs");
			file.deleteOnExit();
			FileWriter fw = new java.io.FileWriter(file);

			String vbs = "Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\n"
					+ "Set colDrives = objFSO.Drives\n" + "Set objDrive = colDrives.item(\"" + drive + "\")\n"
					+ "Wscript.Echo objDrive.SerialNumber"; // see note
			fw.write(vbs);
			fw.close();
			String path = file.getPath().replace("%20", " ");
			Process p = Runtime.getRuntime().exec("cscript //NoLogo " + path);
			BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String line;
			while ((line = input.readLine()) != null) {
				result += line;
			}
			input.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result.trim();
	}

	/**
	 * 获取CPU序列号
	 * 
	 * @return
	 */
	public static String doCPU序列号() {
		String result = "";
		if (isLinux())
			return getLinux序列号("dmidecode -t processor | grep 'ID'", "ID", ":");
		try {
			File file = File.createTempFile("tmp", ".vbs");
			file.deleteOnExit();
			FileWriter fw = new java.io.FileWriter(file);
			String vbs = "Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
					+ "Set colItems = objWMIService.ExecQuery _ \n" + "   (\"Select * from Win32_Processor\") \n"
					+ "For Each objItem in colItems \n" + "    Wscript.Echo objItem.ProcessorId \n"
					+ "    exit for  ' do the first cpu only! \n" + "Next \n";

			// + " exit for \r\n" + "Next";
			fw.write(vbs);
			fw.close();
			String path = file.getPath().replace("%20", " ");
			Process p = Runtime.getRuntime().exec("cscript //NoLogo " + path);
			BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
			String line;
			while ((line = input.readLine()) != null) {
				result += line;
			}
			input.close();
			file.delete();
		} catch (Exception e) {
			e.fillInStackTrace();
		}
		if (result.trim().length() < 1 || result == null) {
			result = "无CPU_ID被读取";
		}
		return result.trim();
	}

	private static List<String> do本机局域网IP4() throws UnknownHostException, SocketException {

		List<String> ips = new ArrayList<String>();
		Enumeration<NetworkInterface> interfs = NetworkInterface.getNetworkInterfaces();
		while (interfs.hasMoreElements()) {
			NetworkInterface interf = interfs.nextElement();
			Enumeration<InetAddress> addres = interf.getInetAddresses();
			while (addres.hasMoreElements()) {
				InetAddress in = addres.nextElement();
				if (in instanceof Inet4Address) {
					// System.out.println("v4:" + in.getHostAddress());
					if (!"127.0.0.1".equals(in.getHostAddress())) {
						ips.add(in.getHostAddress());
					}
				}
			}
		}
		return ips;
	}

	/**
	 * MAC 通过jdk自带的方法,先获取本机所有的ip,然后通过NetworkInterface获取mac地址
	 * 
	 * @return
	 */
	public static String do网卡地址() {
		if (isLinux())
			return getLinux序列号("ifconfig -a", "ether", " ");
		try {
			String resultStr = "";
			List<String> ls = do本机局域网IP4();
			for (String str : ls) {
				InetAddress ia = InetAddress.getByName(str);// 获取本地IP对象
				// 获得网络接口对象（即网卡），并得到mac地址，mac地址存在于一个byte数组中。
				byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
				// 下面代码是把mac地址拼装成String
				StringBuilder sb = new StringBuilder();
				for (int i = 0; i < mac.length; i++) {
					if (i != 0) {
						sb.append("-");
					}
					// mac[i] & 0xFF 是为了把byte转化为正整数
					String s = Integer.toHexString(mac[i] & 0xFF);
					sb.append(s.length() == 1 ? 0 + s : s);
				}
				// 把字符串所有小写字母改为大写成为正规的mac地址并返回
				resultStr += sb.toString().toUpperCase() + ",";
			}
			return resultStr;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	/*************************** linux *********************************/

	public static String execLinuxCmd(String cmd) {
		try {
			// System.out.println("got cmd job : " + cmd);
			Runtime run = Runtime.getRuntime();
			Process process;
			process = run.exec(cmd);
			InputStream in = process.getInputStream();
			// BufferedReader bs = new BufferedReader(new InputStreamReader(in));
			StringBuffer out = new StringBuffer();
			byte[] b = new byte[8192];
			for (int n; (n = in.read(b)) != -1;) {
				out.append(new String(b, 0, n));
			}

			in.close();
			process.destroy();
			return out.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 
	 * @param cmd    命令语句
	 * @param record 要查看的字段
	 * @param symbol 分隔符
	 * @return
	 */
	public static String getLinux序列号(String cmd, String record, String symbol) {
		String execResult = execLinuxCmd(cmd);
		String[] infos = execResult.split("\n");

		for (String info : infos) {
			info = info.trim();
			if (info.indexOf(record) != -1) {
				info.replace(" ", "");
				String[] sn = info.split(symbol);
				return sn[1];
			}
		}

		return null;
	}

	static boolean isLinux() {
		String os = System.getProperty("os.name");
		os = os.toUpperCase();
		if (os.startsWith("L"))
			return true;
		else
			return false;
	}
	//
	//xAWs1VJSN0I6AMwNMkjEFwscuUB4MFj+3M4dddNGleA=
	
	//YzQwNWFjZDU1MjUyMzc0MjNhMDBjYzBkMzI0OGM0MTcwYjFjYjk0MDc4MzA1OGZlZGNjZTFkNzVkMzQ2OTVlMA==
	public String getUU() {
		return uu;
	}

	String hash = null;
	public String getHash(int 十六进制编码方式) {
		if (hash == null)
			hash = MyHash.getInsSHA256().set转16进制方式(十六进制编码方式).parse(uu);
		return hash;
	}
	public String getHash() {
		if (hash == null)
			hash = MyHash.getInsSHA256().parse(uu);
		return hash;
	}
	byte[] hashbytes=null;
	public byte[] getHashBytes() {
		if (hashbytes == null)
			hashbytes = MyHash.getInsSHA256().digest(uu);
		return hashbytes;
	}
	public byte[] getHashBytes(int 十六进制编码方式) {
		if (hashbytes == null)
			hashbytes = MyHash.getInsSHA256().set转16进制方式(十六进制编码方式).digest(uu);
		return hashbytes;
	}
	/**
	 * 获取CPUID、硬盘序列号、MAC地址、主板序列号
	 * 
	 * @return
	 */
	public Map<String, String> getAllSn() {

		Map<String, String> snVo = new HashMap<String, String>();

		// System.out.println("CPU SN:" + cpuid);
		// System.out.println("主板 SN:" + mainboard);
		// System.out.println("C盘 SN:" + disk);
		// System.out.println("MAC SN:" + mac);

		snVo.put("CPU", cpuid.toUpperCase().replace(" ", ""));
		snVo.put("磁盘", disk.toUpperCase().replace(" ", ""));
		snVo.put("网卡", mac.toUpperCase().replace(" ", ""));
		snVo.put("主板", mainboard.toUpperCase().replace(" ", ""));

		return snVo;
	}

}
